<template>
  <CrudLayout>
    <!-- 搜索区域左侧 -->
    <template #search-left>
      <CrudSearchForm v-model="searchParams" :fields="searchFields" @search="handleSearch" @reset="handleSearchReset" />
    </template>

    <!-- 搜索区域右侧 -->
    <template #search-right>
      <CrudButton v-has="config.actions?.add?.permission" type="add" :icon="config.actions?.add?.icon" size="default"
        @click="handleAddBrand">
        {{ config.actions?.add?.text ?? '新增' }}
      </CrudButton>
    </template>

    <!-- 表格区域 -->
    <template #table-data>
      <CrudDataTable :data="tableData" :columns="tableColumns" v-loading="loading" :height="tableHeight"
        @selection-change="handleSelectionChange" stripe border>
        <!-- 角色列插槽 -->
        <template #roles="{ row }">
          {{ (row as any).roles?.join(', ') || '' }}
        </template>
      </CrudDataTable>
    </template>

    <!-- 底部左侧 -->
    <template #foot-left>
      <CrudButton v-has="config.actions?.batchDelete?.permission" type="batch-delete"
        :icon="config.actions?.batchDelete?.icon" :disabled="selectedRows.length === 0" @click="handleBatchDelete">
        {{ config.actions?.batchDelete?.text ?? '批量删除' }}
      </CrudButton>
      <span v-if="selectedRows.length > 0" class="selection-info">
        已选择 {{ selectedRows.length }} 项
      </span>
    </template>

    <!-- 底部右侧 -->
    <template #footer-right>
      <CrudPagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"
        :total="pagination.total" :page-sizes="config.pagination?.pageSizes" @size-change="handleSizeChange"
        @current-change="loadTableData" />
    </template>
  </CrudLayout>

  <!-- 弹窗容器 -->
  <div class="dialog-container">
    <!-- 编辑弹窗 -->
    <CrudFormDialog ref="editDialogRef" v-model:visible="editDialogVisible" :title="config.form.editTitle"
      :loading="editSubmitLoading" :form-config="formConfig" :model-value="editFormData"
      @update:model-value="handleEditFormUpdate" @submit="handleEditSubmit" @cancel="handleEditDialogClose" />

    <!-- 新增弹窗 -->
    <CrudFormDialog ref="addDialogRef" v-model:visible="addDialogVisible" :title="config.form.addTitle"
      :loading="addSubmitLoading" :form-config="formConfig" :model-value="addFormData"
      @update:model-value="handleAddFormUpdate" @submit="handleAddSubmit" @cancel="handleAddDialogClose" />

    <!-- 删除确认弹窗 -->
    <CrudConfirmDialog v-model:visible="deleteDialogVisible" :loading="deleteLoading" preset="deleteConfirm"
      :delete-type="deleteType" :target-name="getTargetName(deleteTarget)" :selected-count="selectedRows.length"
      @confirm="confirmDelete" @cancel="handleDeleteDialogClose" />

    <!-- 重置密码确认弹窗 -->
    <CrudConfirmDialog v-model:visible="resetPasswordDialogVisible" :loading="resetPasswordLoading" preset="warning"
      :title="`重置密码 - ${getTargetName(resetPasswordTarget)}`"
      :content="config.messages?.resetPasswordConfirm"
      @confirm="confirmResetPassword" @cancel="handleResetPasswordDialogClose" />

    <!-- 分配角色抽屉 -->
    <CrudDrawer v-model="roleDrawerVisible" :title="`分配角色 - ${currentUserUsername || ''}`" direction="rtl" size="500px"
      @confirm="confirmAssignRoles" @cancel="closeAssignDrawer">
      <div class="assign-roles" v-loading="assignRoleDataLoading">
        <div class="assign-roles__header">
          <div class="assign-roles__title">角色分配</div>
          <div class="assign-roles__divider"></div>
        </div>
        <div class="assign-roles__user">
          <span class="assign-roles__user-label">账号：</span>
          <strong class="assign-roles__user-name">{{ currentUserUsername }}</strong>
        </div>
        <div class="assign-roles__controls">
          <CrudCheckbox v-model="checkAll" :indeterminate="isIndeterminate" label="全选" @change="onCheckAllChange" />
        </div>
        <el-checkbox-group v-model="assignRoles" class="assign-roles__group">
          <el-checkbox v-for="role in allRoles" :key="role.id" :label="role.name" :value="role">
            {{ role.name }}
          </el-checkbox>
        </el-checkbox-group>
      </div>
    </CrudDrawer>
  </div>
</template>

<script setup lang="ts">
import type { SearchField } from '@/components/crudstyle/CrudSearchForm/index.vue'
import CrudSearchForm from '@/components/crudstyle/CrudSearchForm/index.vue'
import { ElMessage } from 'element-plus'
import { computed, onMounted, reactive, ref } from 'vue'

import type { TableRowData } from '@/components/cruddata/CrudDataTable/types'
import type { FormConfig } from '@/components/cruddata/CrudFormDialog/types'
import { useSettingStore, useUserStore } from '@/stores'
import config from './config'
import pageApi from './page.api'
import type { FormData, Pagination, Records, RoleItem } from './page.type'

// #region 搜索区域
// 设置仓库
const settingStore = useSettingStore()

// 从配置文件中获取搜索字段配置
const searchFields = config.search.fields as SearchField[]

// 搜索参数
const searchParams = ref<Record<string, unknown>>({
  username: '',
  name: '',
})

// 搜索处理
const handleSearch = () => {
  // 重置页码并加载数据
  pagination.currentPage = 1
  loadTableData()
}

// 重置搜索
const handleSearchReset = async () => {
  // 重置为空字符串
  searchParams.value.username = ''
  searchParams.value.name = ''
  await settingStore.triggerRefresh()
}

// #endregion

// mount前加载数据
onMounted(async () => {
  await loadTableData()
  // 可在进入页面时按需预加载
})

// #region 表格数据
// 表格数据加载中状态
const loading = ref(false)

// 表格数据
const tableData = ref<Records[]>([])

// 表格列配置，添加操作列
const tableColumns = computed(() => {
  const userButtons = userStore.userInfo?.buttons || []

  // 定义所有操作按钮
  const allActions = [
    {
      text: '编辑',
      label: '编辑',
      type: 'primary' as const,
      size: 'small' as const,
      plain: true,
      permission: 'btn.User.update',
      handler: (row: TableRowData) => handleEdit(row as unknown as Records)
    },
    {
      text: '删除',
      label: '删除',
      type: 'danger' as const,
      size: 'small' as const,
      plain: true,
      permission: 'btn.User.remove',
      handler: (row: TableRowData) => handleDelete(row as unknown as Records)
    },
    {
      text: '分配角色',
      label: '分配角色',
      type: 'info' as const,
      size: 'small' as const,
      plain: true,
      permission: 'btn.User.assign',
      handler: (row: TableRowData) => openAssignDrawer(row as unknown as Records)
    },
    {
      text: '重置密码',
      label: '重置密码',
      type: 'warning' as const,
      size: 'small' as const,
      plain: true,
      permission: 'btn.User.resetPassword',
      handler: (row: TableRowData) => handleResetPassword(row as unknown as Records)
    },
  ]

  // 根据权限过滤按钮
  const visibleActions = allActions.filter(action =>
    !action.permission || userButtons.includes(action.permission)
  )

  // 如果没有可见按钮，不显示操作列
  if (visibleActions.length === 0) {
    return config.tableColumns
  }

  return [
    ...config.tableColumns,
    {
      type: 'actions',
      label: '操作',
      width: 330,
      align: 'center',
      fixed: 'right',
      actions: visibleActions
    }
  ]
})

// 加载表格数据
const loadTableData = async () => {
  try {
    loading.value = true
    // 过滤空值
    const params = Object.fromEntries(
      Object.entries(searchParams.value).filter(([, value]) => value !== '' && value !== null && value !== undefined)
    )
    const { data } = await pageApi.getList(pagination.currentPage, pagination.pageSize, params)
    console.log('data', data)
    pagination.total = data.data.total
    tableData.value = data.data.records
    ElMessage.success(config.messages?.loadSuccess ?? '加载成功')
  } finally {
    loading.value = false
  }
}

// #endregion

// #region 增删改查（操作列，新增按钮，删除按钮，批量删除按钮，分配角色按钮）

// 表单配置
const formConfig = reactive<FormConfig>({
  labelWidth: config.form.labelWidth,
  rules: config.form.rules as FormConfig['rules'],
  fields: config.form.fields as FormConfig['fields']
})

// #region 编辑按钮
//获取用户信息
const userStore = useUserStore()
// 编辑对话框显示状态
const editDialogVisible = ref(false)
// 编辑对话框引用
const editDialogRef = ref<{ clearValidate: () => void } | null>(null)
// 编辑表单数据
const editFormData = reactive<FormData>({
  id: '',
  sort: 1,
  status: 'ACTIVE'
})
// 编辑按钮提交加载状态
const editSubmitLoading = ref(false)
// 编辑表单数据更新处理
const handleEditFormUpdate = (value: FormData) => {
  Object.assign(editFormData, value)
}

// 编辑按钮点击
const handleEdit = (row: Records): void => {
  // 创建一个新的对象，确保响应性
  Object.assign(editFormData, row)
  editDialogVisible.value = true
}

// 编辑弹窗确认
const handleEditSubmit = async () => {
  editSubmitLoading.value = true
  try {
    await pageApi.update(editFormData)
    ElMessage.success(config.messages?.editSuccess ?? '修改成功！')
    await loadTableData()
    //只在编辑用户阶段使用：请删除
    if (userStore.userInfo?.id === editFormData.id) {
      await userStore.userInfoReq()
    }
  } finally {
    handleEditDialogClose()
    editSubmitLoading.value = false
  }
}

// 编辑弹窗关闭
const handleEditDialogClose = () => {
  editDialogVisible.value = false
  Object.keys(editFormData).forEach(key => {
    // avoid using `any` by asserting a safer unknown index signature
    delete (editFormData as Record<string, unknown>)[key]
  })
  //清除校验
  editDialogRef.value?.clearValidate()
}

// #endregion

// #region 新增按钮
// 新增对话框显示状态
const addDialogVisible = ref(false)

// 新增对话框引用
const addDialogRef = ref<{ clearValidate: () => void } | null>(null)

// 新增表单数据
const addFormData = reactive<FormData>({
  username: '',
  nickName: '',
  password: '',
  avatar: '',
  sort: 1,
  status: 'ACTIVE',
})

// 对话框提交加载状态
const addSubmitLoading = ref(false)

// 新增表单数据更新处理
const handleAddFormUpdate = (value: FormData) => {
  Object.assign(addFormData, value)
  addFormData.nickName = value.username
  addFormData.password = value.username
}

// 新增按钮点击
const handleAddBrand = () => {
  addDialogVisible.value = true
}

// 新增弹窗确认
const handleAddSubmit = async () => {
  addSubmitLoading.value = true
  try {
    pagination.currentPage = 1
    await pageApi.create(addFormData)
    ElMessage.success(config.messages?.addSuccess ?? '添加成功！')
    await loadTableData()
  } finally {
    handleAddDialogClose()
    addSubmitLoading.value = false
  }
}

// 新增弹窗关闭
const handleAddDialogClose = () => {
  addDialogVisible.value = false
  Object.keys(addFormData).forEach(key => {
    // avoid using `any` by asserting a safer unknown index signature
    delete (addFormData as Record<string, unknown>)[key]
  })
  //清除校验
  addDialogRef.value?.clearValidate()
}

// #endregion

// #region 删除按钮

// 删除确认对话框相关状态
const deleteDialogVisible = ref(false)
const deleteLoading = ref(false)
const deleteType = ref<'single' | 'batch'>('single')
const deleteTarget = ref<Records | null>(null)
const selectedRows = ref<Records[]>([])

// #endregion

// #region 重置密码按钮

// 重置密码确认对话框相关状态
const resetPasswordDialogVisible = ref(false)
const resetPasswordLoading = ref(false)
const resetPasswordTarget = ref<Records | null>(null)

// #endregion

// 获取删除目标名称
const getTargetName = (target: unknown): string => {
  if (!target || !config.page.targetNameField) {
    return ''
  }
  // 修复：直接从 target 对象获取字段，而不是 target.data
  return (target as unknown as Record<string, unknown>)[config.page.targetNameField] as string || ''
}

// 删除按钮
// 单个删除
const handleDelete = (row: Records): void => {
  deleteType.value = 'single'
  deleteTarget.value = row
  deleteDialogVisible.value = true
}

// 批量删除
const handleBatchDelete = (): void => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning('请选择要删除的数据')
    return
  }

  deleteType.value = 'batch'
  deleteTarget.value = null
  deleteDialogVisible.value = true
}

// 弹窗取消按钮
const handleDeleteDialogClose = (): void => {
  deleteDialogVisible.value = false
  deleteTarget.value = null
  deleteLoading.value = false
}

// 弹窗确认删除按钮
const confirmDelete = async (): Promise<void> => {
  deleteLoading.value = true
  try {
    if (deleteType.value === 'single') {
      // 单个删除
      if (!deleteTarget.value) {
        ElMessage.error('删除目标不存在')
        return
      }
      await pageApi.delete(deleteTarget.value.id as string)
      ElMessage.success('删除成功')
    } else {
      // 批量删除
      if (selectedRows.value.length === 0) {
        ElMessage.error('请选择要删除的数据')
        return
      }
      await pageApi.batchDelete(selectedRows.value.map(row => row.id as string))
      ElMessage.success('批量删除成功')
      selectedRows.value = []
    }
    loadTableData()
  } finally {
    handleDeleteDialogClose()
    deleteLoading.value = false
  }
}


// 处理表格选择列变化
const handleSelectionChange = (selection: TableRowData[]): void => {
  // 将TableRowData类型转换为Records类型
  selectedRows.value = selection as unknown as Records[]
  console.log('选中的数据:', selection)
}

// #endregion

// #region 重置密码按钮

// 重置密码按钮
const handleResetPassword = (row: Records): void => {
  resetPasswordTarget.value = row
  resetPasswordDialogVisible.value = true
}

// 弹窗取消按钮
const handleResetPasswordDialogClose = (): void => {
  resetPasswordDialogVisible.value = false
  resetPasswordTarget.value = null
  resetPasswordLoading.value = false
}

// 弹窗确认重置密码按钮
const confirmResetPassword = async (): Promise<void> => {
  if (!resetPasswordTarget.value) {
    ElMessage.error('用户不存在')
    return
  }
  resetPasswordLoading.value = true
  try {
    await pageApi.resetPassword(resetPasswordTarget.value.id as string)
    ElMessage.success(config.messages?.resetPasswordSuccess ?? '密码重置成功')
    loadTableData()
  }
 finally {
    handleResetPasswordDialogClose()
  }
}

// #endregion

// #region 分配角色按钮

// 角色抽屉相关状态
const roleDrawerVisible = ref(false)
const assignRoleDataLoading = ref(false) // 加载数据时的 loading
const currentUserId = ref<string | null>(null)
const currentUserUsername = ref('')
// 角色数据
const allRoles = ref<RoleItem[]>([])
const assignRoles = ref<RoleItem[]>([])
// 全选状态和半选状态
const checkAll = ref(false)
// 半选状态判断
const isIndeterminate = computed(() => {
  const total = allRoles.value.length
  const count = assignRoles.value.length
  return count > 0 && count < total
})
// 全选状态改变
const onCheckAllChange = (val: boolean | string | number) => {
  const checked = Boolean(val)
  // 选中值为角色对象，本处直接赋值对象数组或空数组
  assignRoles.value = checked ? allRoles.value.slice() : []
}

// 打开分配角色抽屉
const openAssignDrawer = async (row: Records) => {
  roleDrawerVisible.value = true
  assignRoleDataLoading.value = true
  try {
    currentUserId.value = row.id as string
    currentUserUsername.value = row.username
    const { data } = await pageApi.assignRole(currentUserId.value)
    allRoles.value = data.data?.allRolesList
    assignRoles.value = data.data?.assignRoles
    checkAll.value = assignRoles.value.length === allRoles.value.length && allRoles.value.length > 0
  } finally {
    assignRoleDataLoading.value = false
  }

}

const closeAssignDrawer = () => {
  allRoles.value = []
  assignRoles.value = []
  checkAll.value = false
  assignRoleDataLoading.value = false
  roleDrawerVisible.value = false
}

const confirmAssignRoles = async () => {
  if (!currentUserId.value) {
    ElMessage.error('用户不存在')
    return
  }
  assignRoleDataLoading.value = true
  try {
    // 提交时转换对象数组为 id 数组
    await pageApi.doAssignRole(currentUserId.value, assignRoles.value.map(r => r.id))
    await loadTableData()
    ElMessage.success('分配成功')
  } finally {
    closeAssignDrawer()
  }
}
// #endregion

// #endregion

// #region 底部分页组件

// 分页信息
const pagination = reactive<Pagination>({
  currentPage: 1,
  pageSize: config.pagination?.defaultPageSize || 10,
  total: 0
})

// 处理页面展示数据数量size变化
const handleSizeChange = (): void => {
  pagination.currentPage = 1
  loadTableData()
}

// #endregion

// #region 其他通用函数

// 计算表格高度
const tableHeight = computed(() => {
  // 页面可用高度 = 100vh - 64px(header) - 48px(MainContent padding)
  const pageHeight = window.innerHeight - 64 - 48

  // 搜索区域高度：padding(20px*2) + margin-bottom(20px) + 内容高度(约40px) = 80px
  const searchSectionHeight = 80

  // 表格底部操作区域高度：padding(15px*2) + border(1px) + 内容高度(约30px) = 61px
  const tableFooterHeight = 61

  // 预留一些空间避免滚动条
  const reservedHeight = 10

  const calculatedHeight = pageHeight - searchSectionHeight - tableFooterHeight - reservedHeight

  // 确保最小高度
  const finalHeight = Math.max(calculatedHeight, 300)

  return `${finalHeight}px`
})

// #endregion


</script>

<style scoped lang="scss">
/* 分配角色抽屉样式 */
.assign-roles {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.assign-roles__header {
  margin-bottom: 24px;
}

.assign-roles__title {
  font-size: $home-font-size-medium;
  font-weight: 600;
  color: $text-color-primary;
  margin-bottom: 12px;
}

.assign-roles__divider {
  height: 2px;
  background: linear-gradient(to right, $primary-color, transparent);
  border-radius: 1px;
}

.assign-roles__user {
  display: flex;
  align-items: center;
  padding: 16px;
  background: $bg-color-light;
  border-radius: 8px;
  margin-bottom: 20px;
  border-left: 3px solid $primary-color;
}

.assign-roles__user-label {
  color: $text-color-secondary;
  font-size: $home-font-size-normal;
}

.assign-roles__user-name {
  color: var(--primary-color, $primary-color);
  font-size: 15px;
  margin-left: 4px;
}

.assign-roles__controls {
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px dashed $border-color-light;
}

.assign-roles__group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.assign-roles__group :deep(.el-checkbox) {
  margin-right: 0;
  padding: 10px 12px;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.assign-roles__group :deep(.el-checkbox:hover) {
  background-color: $hover-bg-light;
}

.assign-roles__group :deep(.el-checkbox.is-checked) {
  background-color: var(--primary-color-alpha-10, $primary-color-alpha-10);
}

/* 复选框选中颜色为主题色 */
.assign-roles__group :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
  background-color: var(--primary-color, $primary-color);
  border-color: var(--primary-color, $primary-color);
}

.assign-roles__group :deep(.el-checkbox__input.is-indeterminate .el-checkbox__inner) {
  background-color: var(--primary-color, $primary-color);
  border-color: var(--primary-color, $primary-color);
}

.assign-roles__group :deep(.el-checkbox__input.is-checked .el-checkbox__inner::after) {
  border-color: #fff;
}

.assign-roles__group :deep(.el-checkbox__input.is-focus .el-checkbox__inner) {
  border-color: var(--primary-color, $primary-color);
}

.assign-roles__group :deep(.el-checkbox__input:hover .el-checkbox__inner) {
  border-color: var(--primary-color-hover, $primary-color-hover);
}

/* 复选框文字颜色 */
.assign-roles__group :deep(.el-checkbox.is-checked .el-checkbox__label) {
  color: var(--primary-color, $primary-color);
  font-weight: 500;
}

.assign-roles__group :deep(.el-checkbox:hover .el-checkbox__label) {
  color: var(--primary-color-hover, $primary-color-hover);
}

.assign-roles__group :deep(.el-checkbox__label) {
  color: $text-color-primary;
  transition: color 0.2s ease;
}

.selection-info {
  margin-left: 12px;
  color: $text-color-secondary;
  font-size: $home-font-size-normal;
}

/* 暗黑模式适配 */
@media (prefers-color-scheme: dark) {
  .assign-roles__title {
    color: $text-color-primary-dark;
  }

  .assign-roles__user {
    background: $bg-color-gray-dark;
    border-left-color: var(--primary-color, $primary-color);

    &-label {
      color: $text-color-secondary-dark;
    }

    &-name {
      color: var(--primary-color, $primary-color);
    }
  }

  .assign-roles__controls {
    border-bottom-color: $border-color-base-dark;
  }

  .assign-roles__group :deep(.el-checkbox) {
    &:hover {
      background-color: $hover-bg-light-dark;
    }

    &.is-checked {
      background-color: $active-bg-primary-dark;
    }
  }

  .assign-roles__group :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
    background-color: var(--primary-color, $primary-color);
    border-color: var(--primary-color, $primary-color);
  }

  .assign-roles__group :deep(.el-checkbox__input.is-indeterminate .el-checkbox__inner) {
    background-color: var(--primary-color, $primary-color);
    border-color: var(--primary-color, $primary-color);
  }

  .assign-roles__group :deep(.el-checkbox__input.is-focus .el-checkbox__inner) {
    border-color: var(--primary-color, $primary-color);
  }

  .assign-roles__group :deep(.el-checkbox__input:hover .el-checkbox__inner) {
    border-color: var(--primary-color-hover, $primary-color-hover);
  }

  .assign-roles__group :deep(.el-checkbox.is-checked .el-checkbox__label) {
    color: var(--primary-color, $primary-color);
  }

  .assign-roles__group :deep(.el-checkbox:hover .el-checkbox__label) {
    color: var(--primary-color-hover, $primary-color-hover);
  }

  .assign-roles__group :deep(.el-checkbox__label) {
    color: $text-color-primary-dark;
  }

  .selection-info {
    color: $text-color-secondary-dark;
  }
}
</style>
